#pragma once

#include <utility>
#include "RBTree.hpp"

namespace my
{
	template<class T, class CompareKey = less<T>>
	class set
	{
		typedef const T ConstKeyType;
		typedef T NoConstKeyType;
		typedef T Key;
		typedef T Value;
		
		struct GetSetKey
		{
			const Key& operator()(const ConstKeyType& data) const
			{
				return data;
			}
		};
		typedef RBTree_base<ConstKeyType, Key, NoConstKeyType, GetSetKey, CompareKey> RBTree;
		RBTree _base;

	public:

		typedef typename RBTree::iterator iterator;
		typedef typename RBTree::const_iterator const_iterator;
		typedef typename RBTree::reverse_iterator reverse_iterator;
		typedef typename RBTree::const_reverse_iterator const_reverse_iterator;

		iterator begin()
		{
			return _base.begin();
		}

		iterator end()
		{
			return _base.end();
		}

		const_iterator begin() const
		{
			return _base.begin();
		}

		const_iterator end() const
		{
			return _base.end();
		}

		reverse_iterator rbegin()
		{
			return _base.rbegin();
		}

		reverse_iterator rend()
		{
			return _base.rend();
		}

		const_reverse_iterator rbegin() const
		{
			return _base.rbegin();
		}

		const_reverse_iterator rend() const
		{
			return _base.rend();
		}

	public:

		set() = default;

		template<class InputIterator>
		set(InputIterator begin, InputIterator end)
			:_base(begin, end)
		{
			;
		}

		set(std::initializer_list<ConstKeyType> list)
			:_base(list)
		{
			;
		}

	public:

		bool empty() const
		{
			return _base.size() == 0;
		}

		size_t size() const
		{
			return _base.size();
		}

		const_iterator find(const Key& key) const
		{
			return const_iterator(_base.find(key));
		}

		iterator find(const Key& key)
		{
			return iterator(_base.find(key));
		}

		std::pair<iterator, bool> insert(const ConstKeyType& data)
		{
			bool get = _base.insert(data);
			return { iterator(_base.find(data)), get };
		}

		template <class InputIterator>
		void insert(InputIterator first, InputIterator last)
		{
			while (first != last)
			{
				_base.insert(*first);
				++first;
			}
		}

		void insert(std::initializer_list<ConstKeyType> il)
		{
			for (const ConstKeyType& e : il)
			{
				_base.insert(e);
			}
		}

		size_t erase(const Key& key)
		{
			return _base.erase(key);
		}

		void erase(iterator first, iterator last)
		{
			while (first != last)
			{
				_base.insert(*first);
				++first;
			}
		}

		void clear()
		{
			_base.clear();
		}
	};
}
